package com.zzw.java.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.zzw.java.pojo.DtuDTO;
import com.zzw.java.entity.LevelResult;
import com.zzw.java.pojo.Result;
import com.zzw.java.serial.ReceiveDataHandlerImpl;
import com.zzw.java.service.DtuService;
import com.zzw.java.service.LevelResultService;
import com.zzw.java.utils.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 类描述
 *
 * @author XiaoJie
 * 2025/10/28 15:19
 */
@Slf4j
@Service
public class DtuServiceImpl implements DtuService {

    @Resource
    private LevelResultService levelResultService;

    @Resource
    private RestTemplate restTemplate;

    @Value("${dtu.version-number}")
    private String appVersion;

    @Value("${dtu.url}")
    private String dtuUrl;

    // 目标下载目录（你指定的/media/mmcblk0p1/jar）
    private static final String TARGET_DIR = "/media/mmcblk0p1/jar";
    // 下载超时时间（秒）
    private static final int TIMEOUT_SEC = 1200;
    // 重试次数
    private static final int RETRY_COUNT = 3;

    @Override
    public Boolean restartDtu() {
        Boolean reset;
        try {
            // 执行命令
            Process process = Runtime.getRuntime().exec("/sbin/reboot");
            process.getOutputStream().close();
            reset=Boolean.TRUE;
        } catch (Exception e) {
            reset = Boolean.FALSE;
            log.error("重启异常", e);
        }
        return reset;
    }


    @Override
    public List<LevelResult> queryLevelResults(DtuDTO dto) {
        LambdaQueryWrapper<LevelResult> lambdaQueryWrapper = new LambdaQueryWrapper<LevelResult>()
                .eq(ObjectUtil.isNotEmpty(dto.getUploadStatus()), LevelResult::getUploadStatus, dto.getUploadStatus())
                .orderByDesc(LevelResult::getSurveyTime);
        return  levelResultService.list(lambdaQueryWrapper);
    }

    @Override
    public String getSerialNumber() {
        return ReceiveDataHandlerImpl.TRANSFER_MODULE_MAC;
    }

    @Override
    public Object getDtuRunStatus() {
        return null;
    }

    @Override
    public String getNetworkStatus() {
        String command = null; //命令
        String charset = null; // 流读取的编码
        String[] cmdArray = new String[0];      // 拆分命令为数组
        //判断操作系统类型
        String osName = System.getProperty("os.name").toLowerCase();
        boolean isWindows = osName.contains("win");
        boolean isLinux = osName.contains("nux") || osName.contains("nix");
        if (!isWindows && !isLinux) {
            return "不支持的操作系统：" + osName;
        }
        if (isWindows) {
            command="ping www.baidu.com -n 3";
            charset = "GBK"; // Windows默认编码
        }
        
        if (isLinux) {
            // Linux的ping命令：发送3个包（-c 3），目标百度，指定网卡（可选，如eth0）
            command="ping www.baidu.com -I eth2 -c 3";
            charset = "UTF-8"; // Linux默认编码
        }
        if (!StringUtils.isEmpty(command)) {
            cmdArray = command.split(" "); // 拆分命令为数组
        }
        StringBuilder output = new StringBuilder(); // 存储ping的正常输出
        StringBuilder error = new StringBuilder();  // 存储错误信息（如网卡不存在、网络不通）
        try {
            // 执行命令（Linux推荐用字符串数组传递参数，避免空格解析问题）
            Process process = Runtime.getRuntime().exec(cmdArray);
            // 读取标准输出（Linux默认UTF-8编码，直接使用即可）
            String finalCharset = charset;
            new Thread(() -> readStream(process.getInputStream(), output, finalCharset)).start();
            // 读取错误输出（如命令错误、网卡不存在等）
            String finalCharset1 = charset;
            new Thread(() -> readStream(process.getErrorStream(), error, finalCharset1)).start();

            // 等待命令执行完成，最多等待10秒（防止无限阻塞）
            boolean isFinished = process.waitFor(15, TimeUnit.SECONDS);
            if (!isFinished) {
                process.destroy(); // 超时未完成，强制结束进程
                return "网络不通，请检查（ping命令执行超时（超过15秒）！！！";
            }
            if (process != null) {
                process.destroy(); // 确保进程销毁，释放资源
            }
        } catch (IOException e) {
            return "执行ping命令失败：" + e.getMessage();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 恢复中断状态
            return "线程被中断：" + e.getMessage();
        }
        // 拼接结果（优先显示错误信息，再显示正常输出）
        StringBuilder result = new StringBuilder();
        if (error.length() > 0) {
            result.append("错误信息：\n").append(error).append("\n");
        }
        result.append("输出结果：\n").append(output);
        return result.toString();
    }

    @Override
    public Boolean removeAll() {
        // 清空所有数据
       return levelResultService.remove(new LambdaQueryWrapper<LevelResult>().isNotNull(LevelResult::getId));
    }

    @Override
    public String upgrade() {
        log.info("DTU升级请求URL: {}", dtuUrl);
        String forObject = restTemplate.getForObject(dtuUrl, String.class);
        if (!StrUtil.isBlank(forObject)) {
            Gson gson = GsonUtil.getGson();
            Result result = gson.fromJson(forObject, Result.class);
            if (ObjectUtil.isEmpty(result)||result.getCode()!=0) return "请求失败！请重试";
            if (ObjectUtil.isEmpty(result.getData())||StrUtil.isBlank(result.getData().getApplicationVersion())) return "暂无更新！";
            String applicationUpdateUrl = result.getData().getApplicationUpdateUrl();
            if (StrUtil.isBlank(applicationUpdateUrl)) return "更新失败，安装包地址为空！";
            int remoteVersion;
            int localVersion;
            try {
                remoteVersion = Integer.parseInt(result.getData().getApplicationVersion().replace(".",""));
                localVersion = Integer.parseInt(appVersion.replace(".",""));
            } catch (NumberFormatException e) {
                log.error("版本号格式错误: 远程={}, 本地={}", result.getData().getApplicationVersion(), appVersion);
                return "版本号格式错误";
            }
            if (remoteVersion <= localVersion) {
                log.info("已是最新版本，本地版本: {}, 远程版本: {}", appVersion, result.getData().getApplicationVersion());
                return "已是最新版本，无需更新";
            }
            String fileName = applicationUpdateUrl.substring(applicationUpdateUrl.lastIndexOf("/") + 1);
            log.info("解析下载文件名: {}", fileName);
            File targetDirFile = new File(TARGET_DIR);
            if (!targetDirFile.exists()) return "目标目录不存在: "+TARGET_DIR+"；请检查！";
            // 新增文件存在性检查和删除逻辑
            File targetFile = new File(TARGET_DIR, fileName);
            if (targetFile.exists() && targetFile.isFile()) {
                if (!targetFile.delete()) {
                    log.error("旧文件删除失败: {}", targetFile.getAbsolutePath());
                    return "旧版本文件删除失败";
                }
                log.info("已删除旧版本文件: {}", targetFile.getAbsolutePath());
            }
            // 异步执行升级操作
            CompletableFuture.runAsync(() -> {
                try {
                    // 构建wget命令（下载APK到指定目录）
                    List<String> wgetCommand = new ArrayList<>();
                    wgetCommand.add("wget");
                    wgetCommand.add("-t"); // 重试次数
                    wgetCommand.add(String.valueOf(RETRY_COUNT));
                    wgetCommand.add("-T"); // 超时时间
                    wgetCommand.add(String.valueOf(TIMEOUT_SEC));
                    wgetCommand.add("--no-cache"); // 不使用缓存
                    wgetCommand.add(result.getData().getApplicationUpdateUrl()); // 待下载的APK URL

                    log.info("异步执行命令：" + String.join(" ", wgetCommand));
                    log.info("执行目录：" + TARGET_DIR);

                    // 配置ProcessBuilder：指定工作目录+执行命令
                    ProcessBuilder processBuilder = new ProcessBuilder(wgetCommand);
                    processBuilder.directory(targetDirFile); // 设置命令执行的工作目录
                    processBuilder.redirectErrorStream(true); // 合并错误流到输出流（方便查看日志）

                    // 启动进程并读取输出（防止缓冲区满导致阻塞）
                    Process process = processBuilder.start();
                    readProcessLog(process);

                    // 等待命令完成并校验结果
                    boolean isFinish = process.waitFor(TIMEOUT_SEC, TimeUnit.SECONDS);
                    if (!isFinish) {
                        process.destroyForcibly();
                        log.error("下载超时，已强制终止");
                        return;
                    }

                    // 检查退出码（0表示成功）
                    if (process.exitValue() == 0) {
                        log.info("升级包下载成功");
                    } else {
                        log.error("wget失败，退出码：{}", process.exitValue());
                    }
                } catch (IOException e) {
                    log.error("IO异常: {}", e.getMessage());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("进程被中断: {}", e.getMessage());
                } catch (Exception e) {
                    log.error("升级过程中发生未知错误: {}", e.getMessage());
                }
            });

            // 立即返回，不等待异步操作完成
            return "升级已开始，请稍后查看日志确认结果";
       }
        return "升级失败-未获取到更新信息";
    }

    public static void main(String[] args) {
        String url = "http://mis.zhizhuwang.online/applicationFile/zzwMisViewAppV1.2.7.apk";
        String fileName = url.substring(url.lastIndexOf("/") + 1);
        System.out.println(fileName);
    }
    /**
     * 读取wget执行日志（单独启线程，避免阻塞）
     */
    private static void readProcessLog(Process process) {
        new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info("wget日志：" + line);
                }
            } catch (IOException e) {
                log.error("读取日志失败：" + e.getMessage());
            }
        }).start();
    }
    /**
     * 读取输入流并写入字符串缓冲区（Linux用UTF-8编码）
     */
    private  void readStream(InputStream inputStream, StringBuilder buffer, String charset) {
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(inputStream, charset))) { // Linux默认UTF-8
            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line).append("\n"); // 按行读取并拼接
            }
        } catch (IOException e) {
            buffer.append("读取流失败：").append(e.getMessage()).append("\n");
        }
    }
}
